package com.meida.module.order.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.constants.CommonConstants;
import com.meida.common.enums.OrderStatusEnum;
import com.meida.common.enums.PayStatusEnum;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.OpenHelper;
import com.meida.common.security.OpenUser;
import com.meida.common.utils.*;
import com.meida.module.marketing.provider.service.CouponUserService;
import com.meida.module.order.client.entity.OrderDetails;
import com.meida.module.order.client.entity.OrderInfo;
import com.meida.module.order.client.vo.LeaveMsg;
import com.meida.module.order.provider.mapper.OrderDetailsMapper;
import com.meida.module.order.provider.mapper.OrderInfoMapper;
import com.meida.module.order.provider.service.*;
import com.meida.module.product.client.entity.*;
import com.meida.module.product.provider.service.*;
import com.meida.module.system.client.entity.SysAddress;
import com.meida.module.system.provider.service.SysAddressService;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单接口实现类
 *
 * @author flyme
 * @date 2019-11-27
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class OrderInfoServiceImpl extends BaseServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Resource
    private SysAddressService addressService;

    @Resource
    private OrderLogisticsService logisticsService;

    @Resource
    private OrderDetailsService orderDetailsService;


    @Resource
    private OrderShopcartService orderShopcartService;

    @Resource
    private CouponUserService couponUserService;

    @Resource
    private OrderNoUtil orderNoUtil;

    @Resource
    private ProdSkuService skuService;

    @Resource
    private ProdMarketingService marketingService;


    @Resource
    private ProdShopService prodShopService;


    @Resource
    private ProdProductService productService;

    @Resource
    private OrdInvoiceService invoiceService;

    @Resource
    private OrderAfterserviceService afterserviceService;

    @Resource
    private OrderDetailsMapper detailsMapper;

    @Resource
    private ProdAftersaleService aftersaleService;


    /**
     * 订单列表查询条件(订单列表需配合handler)
     *
     * @param cq
     * @param orderInfo
     * @param requestMap
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<OrderInfo> cq, OrderInfo orderInfo, EntityMap requestMap) {
        cq.select(OrderInfo.class, "orderId", "parentId", "shopId", "companyId", "orderTitle", "orderNo", "userCouponId", "freightAmount", "totalAmount", "couponAmount", "discountAmount", "productCount", "payAmount", "selfState", "parentOrder", "orderState", "payState", "payType", "createTime");
        //只查询子单,排除拆分后已支付的母单
        cq.eq(OrderInfo.class, "showState", CommonConstants.INT_1);
        cq.eq(OrderInfo.class, "orderNo");
        //订单状态筛选
        Integer orderState = requestMap.getInt("orderState", 0);
        if (!orderState.equals(0)) {
            cq.likeRight(true, "orderState", orderState);
        }
        cq.ge(OrderInfo.class, "createTime", cq.getParams("beginDate"));
        cq.le(OrderInfo.class, "createTime", cq.getParams("endDate"));
        cq.orderByDesc("orderinfo.createTime");
        return ResultBody.ok();
    }

    /**
     * 购物车订单提交前处理
     *
     * @param cs
     * @param orderInfo
     * @return
     */
    @Override
    public ResultBody beforeAdd(CriteriaSave cs, OrderInfo orderInfo, EntityMap extra) {
        String couponUserIds = cs.getParams("couponUserIds");
        String leaveMsg = cs.getParams("leaveMsg");
        Long addressId = cs.getParams("addressId");
        ApiAssert.isNotEmpty("收货地址不能为空", addressId);
        Long userId = OpenHelper.getUserId();
        //已选商品(已按店铺分组)
        List<EntityMap> groupList = orderShopcartService.listByUserIdAndGroupShop(userId, couponUserIds);
        ApiAssert.isNotEmpty("商品不存在", groupList);
        //订单总金额
        BigDecimal totalAmount = new BigDecimal("0");
        //总运费
        BigDecimal totalFreight = new BigDecimal("0");
        //总优惠金额
        BigDecimal totalCouponAmount = new BigDecimal("0");
        Integer totalNum = 0;
        //实付金额
        BigDecimal payAmount;
        List<LeaveMsg> leaveMsgList = new ArrayList<>();
        if (FlymeUtils.isNotEmpty(leaveMsg)) {
            leaveMsgList = JsonUtils.toList(leaveMsg, LeaveMsg.class);

        }
        for (EntityMap group : groupList) {
            //店铺订单金额
            BigDecimal shopTotalAmount = group.getBigDecimal("shopTotalAmount");
            //店铺运费
            BigDecimal shopTotalFreight = group.getBigDecimal("shopTotalFreight");
            Integer shopTotalNum = group.getInt("shopTotalNum", 0);
            totalAmount = totalAmount.add(shopTotalAmount);
            totalNum += shopTotalNum;
            totalFreight = totalFreight.add(shopTotalFreight);
            if (groupList.size() == 1) {
                //订单不需要拆分时赋值店铺ID
                orderInfo.setCompanyId(group.getLong("companyId"));
                orderInfo.setShopId(group.get("shopId"));
                //不需要拆分时订单直接设置为子单
                orderInfo.setParentOrder(CommonConstants.DISABLED);
                if (FlymeUtils.isNotEmpty(leaveMsgList)) {
                    orderInfo.setLeaveMsg(leaveMsgList.get(0).getLeaveMsg());
                }
            } else {
                //需要拆分是订单设置为母单
                orderInfo.setParentOrder(CommonConstants.ENABLED);
            }
            orderInfo.setUserCouponId(couponUserIds);

        }

        //计算总优惠金额
        if (FlymeUtils.isNotEmpty(couponUserIds)) {
            EntityMap couponMap = couponUserService.calculateCouponAmount(couponUserIds);
            totalCouponAmount = couponMap.getBigDecimal("totalCouponAmount");
        }
        //应付金额
        payAmount = totalAmount.add(totalFreight).subtract(totalCouponAmount);
        orderInfo.setProductCount(totalNum);
        //普通订单
        orderInfo.setOrderType(1);
        ApiAssert.gezero("商品价格设置错误", payAmount);
        initOrderInfo(orderInfo, payAmount, totalCouponAmount, totalFreight, userId, addressId, totalAmount);
        //传递到afterAdd中
        extra.put("groupList", groupList);
        extra.put("totalNum", totalNum);
        extra.put("leaveMsgList", leaveMsgList);
        return ResultBody.ok();
    }

    /**
     * 保存订单明细,涉及多店铺的拆分订单
     *
     * @param cs
     * @param orderInfo
     * @param extra
     * @return
     */
    @Override
    public ResultBody afterAdd(CriteriaSave cs, OrderInfo orderInfo, EntityMap extra) {
        List<EntityMap> groupList = extra.get("groupList");
        List<LeaveMsg> leaveMsgList = extra.get("leaveMsgList");
        String couponUserIds = cs.getParams("couponUserIds");
        Long userId = OpenHelper.getUserId();
        if (FlymeUtils.isNotEmpty(groupList)) {
            if (groupList.size() == 1) {
                //取出商品列表生成订单明细记录
                EntityMap group = groupList.get(0);
                List<OrderDetails> orderDetailsList = getOrderDetails(null, orderInfo, group);
                orderDetailsService.saveBatch(orderDetailsList);
                //保存收货信息
                logisticsService.add(orderInfo.getReceiveAddressId(), orderInfo.getOrderId());
                //保存发票信息
                invoiceService.addInvoide(orderInfo, cs);
                //删除购物车所选商品
                orderShopcartService.clearByOrderDetails(orderDetailsList, userId);
            } else {
                //保存收货信息
                logisticsService.add(orderInfo.getReceiveAddressId(), orderInfo.getOrderId());
                //购物车中全部商品列表(已按店铺分组,当groupList大于1时说明有多个店铺商品,需要进行拆单操作)
                splitOrder(cs, groupList, orderInfo, couponUserIds, leaveMsgList);
            }
        }

        //修改优惠券为已使用状态
        couponUserService.updateCouponState(couponUserIds, CommonConstants.ENABLED);
        return ResultBody.ok("订单创建成功", orderInfo);
    }


    /**
     * 订单详情
     *
     * @param cq
     * @param result
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public void afterGet(CriteriaQuery cq, EntityMap result) {
        Long receiveAddressId = result.getLong("receiveAddressId");
        Long orderId = result.getLong("orderId");
        Integer parentOrder = result.getInt("parentOrder");
        EntityMap orderLogistics = logisticsService.findByOrderId(orderId);

        //查询订单明细
        List<EntityMap> orderDetailsList = orderDetailsService.listByOrderIdForDetails(orderId, parentOrder);
        Integer evaluatedCount = 0;
        for (EntityMap entityMap : orderDetailsList) {
            evaluatedCount += entityMap.getInt("evaluatedCount", 0);
        }

        result.put("evaluatedCount", evaluatedCount);
        result.put("orderDetailsList", orderDetailsList);

        if (FlymeUtils.isNotEmpty(orderLogistics)) {
            //物流信息
            result.put("orderLogistics", orderLogistics);
        }
        SysAddress receiveAddress = addressService.getById(receiveAddressId);


        if (FlymeUtils.isNotEmpty(receiveAddress)) {
            //收货人信息
            result.put("receiveAddress", receiveAddress);
        }

    }

    /**
     * 购物车商品结算确认(计算优惠金额,运费,设置收货地址,发票等)
     *
     * @param couponUserIds
     * @return
     */
    @Override
    public ResultBody confirm(Map params, String couponUserIds) {
        EntityMap result = new EntityMap();
        Long userId = OpenHelper.getUserId();
        //收货地址
        List<EntityMap> addressList = addressService.listByUserId(userId);
        result.put("addressList", addressList);
        //购物车已选商品(已按店铺分组)
        List<EntityMap> groupList = orderShopcartService.listByUserIdAndGroupShop(userId, null);
        result.put("groupList", groupList);

        //订单总金额
        BigDecimal totalAmount = new BigDecimal("0");
        //总运费
        BigDecimal totalFreight = new BigDecimal("0");
        //总优惠金额
        BigDecimal totalCouponAmount = new BigDecimal("0");
        //商品总件数
        Integer totalNum = 0;
        //实付金额
        BigDecimal payAmount;
        for (EntityMap group : groupList) {
            BigDecimal shopTotalAmount = group.getBigDecimal("shopTotalAmount");
            BigDecimal shopTotalFreight = group.getBigDecimal("shopTotalFreight");
            totalNum = group.getInt("shopTotalNum", 0);
            totalAmount = totalAmount.add(shopTotalAmount);
            totalFreight = totalFreight.add(shopTotalFreight);
        }
        //计算总优惠金额
        if (FlymeUtils.isNotEmpty(couponUserIds)) {
            EntityMap couponMap = couponUserService.calculateCouponAmount(couponUserIds);
            totalCouponAmount = couponMap.getBigDecimal("totalCouponAmount");
            couponUserIds = couponMap.get("couponUserIds");
        }
        EntityMap couponList = orderShopcartService.selectCouponList(userId);
        //可用优惠券数量
        Integer couponCount = couponList.getInt("mayYesCount", 0);
        String couponText = "";
        if (couponCount > 0 && FlymeUtils.isEmpty(couponUserIds)) {
            couponText = couponCount + "张可用";
        }
        if (couponCount == 0) {
            couponText = "无可用";
        }
        if (couponCount > 0 && FlymeUtils.isNotEmpty(couponUserIds)) {
            couponText = "优惠: ¥" + totalCouponAmount.toString();
        }
        result.put("couponText", couponText);
        payAmount = totalAmount.add(totalFreight).subtract(totalCouponAmount);
        if (FlymeUtils.ltzero(payAmount)) {
            payAmount = new BigDecimal("0.01");
        }
        result.put("totalAmount", totalAmount);
        result.put("totalFreight", totalFreight);
        result.put("payAmount", payAmount);
        result.put("totalNum", totalNum);
        result.put("couponUserIds", couponUserIds);
        result.put("couponCount", couponCount);
        result.put("totalCouponAmount", totalCouponAmount);
        return ResultBody.ok(result);
    }


    /**
     * 取消订单
     *
     * @param map
     * @return
     */
    @Override
    public ResultBody closeOrder(Map map) {
        CriteriaUpdate cu = new CriteriaUpdate(map, OrderInfo.class);
        Long orderId = cu.getLong("orderId");
        ApiAssert.isNotEmpty("订单ID不能为空", orderId);
        OrderInfo orderInfo = getById(orderId);
        //只有未取消状态才可操作
        cu.set(true, "orderState", OrderStatusEnum.CLOSE.code);
        ResultBody resultBody = baseUpdate(cu);
        if (resultBody.isOk()) {
            //还原优惠券使用状态
            couponUserService.updateCouponState(orderInfo.getUserCouponId(), CommonConstants.DISABLED);
            return ResultBody.msg("取消成功");
        } else {
            return ResultBody.failed("取消失败");
        }
    }


    /**
     * 确认发货
     *
     * @param orderId
     * @return
     */
    @Override
    public ResultBody setLogisticsState(Long orderId) {

        CriteriaUpdate cu = new CriteriaUpdate();
        ApiAssert.isNotEmpty("订单ID不能为空", orderId);
        cu.eq(true, "orderId", orderId);
        cu.eq(true, "orderState", OrderStatusEnum.UNSEND.code);
        cu.set(true, "orderState", OrderStatusEnum.UNRECEIVE.code);
        ResultBody resultBody = baseUpdate(cu);
        return ResultBody.msg("操作成功");
    }


    /**
     * 确认收货
     *
     * @param map
     * @return
     */
    @Override
    public ResultBody receiveOrder(Map map) {
        CriteriaUpdate cu = new CriteriaUpdate(map, OrderInfo.class);
        Long orderId = cu.getLong("orderId");
        ApiAssert.isNotEmpty("订单ID不能为空", orderId);
        //只有已发货状态才可操作
        cu.eq("orderState", OrderStatusEnum.UNRECEIVE.code);
        //修改订单为待评价
        cu.set(true, "orderState", OrderStatusEnum.FINISHED.code);
        ResultBody resultBody = baseUpdate(cu);
        if (resultBody.isOk()) {
            return ResultBody.msg("收货成功");
        } else {
            return ResultBody.failed("操作失败");
        }
    }

    /**
     * 删除订单
     *
     * @param map
     * @return
     */
    @Override
    public ResultBody deleteOrder(Map map) {
        CriteriaUpdate cu = new CriteriaUpdate(map, OrderInfo.class);
        Long orderId = cu.getLong("orderId");
        ApiAssert.isNotEmpty("订单ID不能为空", orderId);
        cu.set(true, "deleted", CommonConstants.DEL_YES);
        //只有未删除状态才可操作
        cu.eq("deleted", CommonConstants.DEL_NO);
        ResultBody resultBody = baseUpdate(cu);
        if (resultBody.isOk()) {

            return ResultBody.msg("删除成功");
        } else {
            return ResultBody.failed("删除失败");
        }
    }

    /**
     * 店铺评分
     *
     * @param orderId
     * @param shopScore
     */
    @Override
    public void setShopScore(Long orderId, Integer shopScore) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "shopScore", shopScore);
        cu.eq(true, "shopScore", 0);
        cu.eq(true, "orderId", orderId);
        update(cu);
    }

    /**
     * 根据订单号查询订单
     *
     * @param orderNo
     * @return
     */
    @Override
    public OrderInfo findByOrderNo(String orderNo) {
        CriteriaQuery cq = new CriteriaQuery(OrderInfo.class);
        cq.eq(true, "orderNo", orderNo);
        return getOne(cq);
    }

    /**
     * 支付成功后修改订单支付状态
     *
     * @param outTradeNo
     * @param orderState
     */
    @Override
    public Boolean paySuccess(String outTradeNo, Map<String, Object> context, Integer orderState) {
        OrderInfo orderInfo = findByOrderNo(outTradeNo);
        if (FlymeUtils.isNotEmpty(orderInfo)) {
            Integer payStatus = orderInfo.getPayState();
            Integer orderType = FlymeUtils.getInteger(orderInfo.getOrderType(), 1);
            //默认是母单
            Integer parentOrder = FlymeUtils.getInteger(orderInfo.getParentOrder(), 0);
            String payTime = DateUtils.getDateTime();
            if (payStatus.equals(PayStatusEnum.NOPAY.getCode())) {
                UpdateWrapper update = new UpdateWrapper();
                update.set(true, "payState", PayStatusEnum.PAY.code);
                update.set(true, "payTime", payTime);
                update.set(true, "orderState", orderState);
                update.set(true, "payType", context.get("payType"));
                update.eq(true, "orderId", orderInfo.getOrderId());
                if (parentOrder.equals(CommonConstants.ENABLED)) {
                    //支付成功后隐藏父单
                    update.set(true, "showState", CommonConstants.DISABLED);
                }
                update(update);
                if (orderType.equals(1)) {
                    detailsMapper.updateSaleCountByOrderId(orderInfo.getOrderId());
                } else {
                    detailsMapper.updateMarketingSaleCountByOrderId(orderInfo.getOrderId());
                }
            }
            //更新子单支付状态
            if (payStatus.equals(PayStatusEnum.NOPAY.getCode()) && parentOrder.equals(CommonConstants.ENABLED)) {
                UpdateWrapper update = new UpdateWrapper();
                update.set(true, "payState", PayStatusEnum.PAY.code);
                update.set(true, "payTime", payTime);
                update.set(true, "payType", context.get("payType"));
                update.set(true, "showState", CommonConstants.ENABLED);
                //支付成功后显示子单
                update.set(true, "orderState", orderState);
                update.eq(true, "parentId", orderInfo.getOrderId());
                update(update);
                if (orderType.equals(1)) {
                    detailsMapper.updateSaleCountByParentOrderId(orderInfo.getOrderId());
                } else {
                    detailsMapper.updateMarketingSaleCountByParentOrderId(orderInfo.getOrderId());
                }
            }
        }

        return true;
    }

    /**
     * 构建订单明细
     */
    private List<OrderDetails> getOrderDetails(OrderInfo parentOrder, OrderInfo orderInfo, EntityMap group) {
        Long companyId = group.getLong("companyId");
        Long shopId = group.getLong("shopId");
        Long userId = OpenHelper.getUserId();
        List<EntityMap> shopCardList = group.get("shopCardList");
        List<OrderDetails> orderDetailsList = new ArrayList<>();
        for (EntityMap shopCard : shopCardList) {
            OrderDetails orderDetails = new OrderDetails();
            orderDetails.setCompanyId(companyId);
            orderDetails.setShopId(shopId);
            if (FlymeUtils.isNotEmpty(parentOrder)) {
                orderDetails.setParentOrderId(parentOrder.getOrderId());
            }
            orderDetails.setOrderId(orderInfo.getOrderId());
            orderDetails.setSkuId(shopCard.getLong("skuId"));
            orderDetails.setEvaluatedState(CommonConstants.DISABLED);
            orderDetails.setAfterSaleState(CommonConstants.DISABLED);
            Long categoryId1 = shopCard.get("categoryId1");
            Long categoryId2 = shopCard.get("categoryId2");
            Long categoryId3 = shopCard.get("categoryId3");
            orderDetails.setCategoryId1(categoryId1);
            orderDetails.setCategoryId2(categoryId2);
            orderDetails.setCategoryId3(categoryId3);
            orderDetails.setUserId(userId);
            orderDetails.setProductId(shopCard.getLong("productId"));
            orderDetails.setProductPrice(shopCard.getBigDecimal("price"));
            orderDetails.setProductNum(shopCard.getInt("buyNum", 1));

            orderDetails.setProductImages(shopCard.get("images"));
            orderDetails.setProductAmount(shopCard.getBigDecimal("price").multiply(new BigDecimal(shopCard.getInt("buyNum", 1))));
            orderDetails.setProductTitle(shopCard.get("title"));
            orderDetails.setSkuTitle(shopCard.get("skuTitle"));
            orderDetailsList.add(orderDetails);
        }
        return orderDetailsList;
    }


    /**
     * 拆分订单
     */
    private void splitOrder(CriteriaSave cs, List<EntityMap> groupList, OrderInfo parentOrder, String couponUserIds, List<LeaveMsg> leaveMsgList) {
        Long userId = OpenHelper.getUserId();
        List<OrderInfo> orderList = new ArrayList<>();
        List<OrderDetails> orderDetailsList = new ArrayList<>();
        for (EntityMap group : groupList) {
            OrderInfo orderInfo = new OrderInfo();
            Long shopId = group.get("shopId");

            orderInfo.setOrderId(IdWorker.getId());
            BigDecimal shopCouponAmount = new BigDecimal("0");
            //计算店铺订单优惠金额
            if (FlymeUtils.isNotEmpty(couponUserIds)) {
                EntityMap shopCouponMap = couponUserService.calculateCouponAmount(couponUserIds, shopId);
                List<Long> shopCouponUserIds = shopCouponMap.get("shopCouponUserIds");
                if (FlymeUtils.isNotEmpty(shopCouponUserIds)) {
                    //记录使用优惠券ID
                    orderInfo.setUserCouponId(StringUtils.join(shopCouponUserIds.toArray(), ","));
                }
                shopCouponAmount = shopCouponMap.getBigDecimal("totalCouponAmount");
            }

            BigDecimal shopTotalAmount = group.getBigDecimal("shopTotalAmount");
            BigDecimal shopTotalFreight = group.getBigDecimal("shopTotalFreight");
            Integer shopTotalNum = group.getInt("shopTotalNum", 0);
            orderInfo.setTotalAmount(shopTotalAmount);
            orderInfo.setFreightAmount(shopTotalFreight);
            orderInfo.setCompanyId(group.getLong("companyId"));
            orderInfo.setShopId(shopId);
            orderInfo.setCompanyId(shopId);
            //应付金额
            BigDecimal payAmount = shopTotalAmount.add(shopTotalFreight).subtract(shopCouponAmount);
            orderInfo.setOrderId(IdWorker.getId());
            //父订单ID
            orderInfo.setParentId(parentOrder.getOrderId());
            //子单商品数量
            orderInfo.setProductCount(shopTotalNum);
            //子单
            orderInfo.setParentOrder(CommonConstants.DISABLED);
            //应付金额
            orderInfo.setPayAmount(payAmount);
            //优惠金额
            orderInfo.setCouponAmount(shopCouponAmount);
            //运费
            orderInfo.setFreightAmount(shopTotalFreight);
            //普通订单
            orderInfo.setOrderType(1);
            orderInfo.setShopScore(CommonConstants.INT_0);
            //下单人
            orderInfo.setUserId(parentOrder.getUserId());
            //买家收货地址
            orderInfo.setReceiveAddressId(parentOrder.getReceiveAddressId());
            orderInfo.setOrderNo(orderNoUtil.getOrderNo());
            //未删除
            orderInfo.setDeleted(CommonConstants.DEL_NO);
            //待付款
            orderInfo.setOrderState(OrderStatusEnum.UNPAY.getCode());
            //默认展示,如有拆分则修改为母单
            orderInfo.setShowState(CommonConstants.DISABLED);
            //订单总金额
            orderInfo.setTotalAmount(shopTotalAmount);
            //未支付
            orderInfo.setPayState(PayStatusEnum.NOPAY.getCode());
            if (FlymeUtils.isNotEmpty(leaveMsgList)) {
                for (LeaveMsg leaveMsg : leaveMsgList) {
                    Long id = leaveMsg.getShopId();
                    if (id.equals(shopId)) {
                        orderInfo.setLeaveMsg(leaveMsg.getLeaveMsg());
                    }
                }
            }
            orderList.add(orderInfo);
            //计算订单明细
            orderDetailsList.addAll(getOrderDetails(parentOrder, orderInfo, group));

            //保存收货信息
            logisticsService.add(orderInfo.getReceiveAddressId(), orderInfo.getOrderId());
            //保存发票信息
            invoiceService.addInvoide(orderInfo, cs);

        }
        this.saveBatch(orderList);
        orderDetailsService.saveBatch(orderDetailsList);
        //删除购物车所选商品
        orderShopcartService.clearByOrderDetails(orderDetailsList, userId);
    }


    /**
     * 普通商品直接购买提交前校验
     *
     * @param params      请求参数
     * @param marketingId 优惠券ID,多个逗号隔开
     * @return
     */
    @Override
    public ResultBody check(Map params, Long marketingId) {
        Long userId = OpenHelper.getUserId();
        ProdMarketing marketing = marketingService.getById(marketingId);
        Integer marketingType = marketing.getMarketingType();
        if (marketingType.equals(1)) {
            Integer count = orderDetailsService.checkMarketingProduct(marketingId, userId);
            ApiAssert.lezero("商品仅限购买一次", count);
        }
        return ResultBody.ok();
    }


    /**
     * 普通商品直接购买提交前确认(计算优惠金额,运费,设置收货地址,发票等)
     *
     * @param params        请求参数
     * @param couponUserIds 优惠券ID,多个逗号隔开
     * @param skuId         商品规格Id
     * @return
     */
    @Override
    public ResultBody confirm(Map params, Long skuId, Long marketingId, Integer buyNum, String couponUserIds) {
        EntityMap result;
        //加锁避免避免超卖情况
        RLock lock = redisLock.lock(skuId);
        try {
            Long userId = OpenHelper.getUserId();
            String numType = "num";
            ApiAssert.isNotEmpty("商品ID不能为空", skuId);
            result = skuService.findById(skuId);
            BigDecimal price = result.getBigDecimal("price");
            if (FlymeUtils.isNotEmpty(marketingId)) {
                ProdMarketing marketing = marketingService.getById(marketingId);
                Integer marketingType = marketing.getMarketingType();
                if (marketingType.equals(1)) {
                    Integer count = orderDetailsService.checkMarketingProduct(marketingId, userId);
                    ApiAssert.lezero("商品仅限购买一次", count);
                }
                //秒杀限购的取秒杀库存
                numType = "seckillNum";
                price = marketing.getMarketingPrice();
            }
            ApiAssert.isNotEmpty("购买数量不能为空", buyNum);
            ApiAssert.gtzero("至少购买一件!", buyNum);


            ApiAssert.isNotEmpty("规格不存在", result);
            Integer num = result.getInt(numType, 0);

            if (num < buyNum) {
                ApiAssert.failure("库存不足!");
            }
            //修改库存
            skuService.updateNum(skuId, numType, num - buyNum);

            Long productId = result.getLong("productId");
            ProdProduct prodProduct = productService.getById(productId);


            String images = result.get("images");
            if (FlymeUtils.isEmpty(images) || images.length() < 10) {
                images = prodProduct.getCoverImage();
                result.put("images", images);
            }
            ApiAssert.isNotEmpty("商品不存在", prodProduct);

            Long shopId = prodProduct.getShopId();

            ApiAssert.isNotEmpty("店铺不存在", shopId);

            ProdShop prodShop = prodShopService.getById(shopId);


            BigDecimal totalCouponAmount = new BigDecimal("0");
            BigDecimal totalAmount = price.multiply(new BigDecimal(buyNum));
            BigDecimal totalFreight = FlymeUtils.getBigDecimal(prodProduct.getFreight(), "0");

            //计算总优惠金额
            if (FlymeUtils.isNotEmpty(couponUserIds)) {
                EntityMap couponMap = couponUserService.calculateCouponAmount(couponUserIds, shopId);
                totalCouponAmount = couponMap.getBigDecimal("totalCouponAmount");
            }
            BigDecimal payAmount = totalAmount.add(totalFreight).subtract(totalCouponAmount);
            EntityMap couponList = couponList(skuId, buyNum, userId);
            //可用优惠券数量
            Integer couponCount = couponList.getInt("mayYesCount", 0);
            String couponText = "";
            if (couponCount > 0 && FlymeUtils.isEmpty(couponUserIds)) {
                couponText = couponCount + "张可用";
            }
            if (couponCount == 0) {
                couponText = "无可用";
            }
            if (couponCount > 0 && FlymeUtils.isNotEmpty(couponUserIds)) {
                couponText = "优惠: ¥" + totalCouponAmount.toString();
            }
            result.put("couponText", couponText);
            //收货地址
            List<EntityMap> addressList = addressService.listByUserId(userId);
            result.put("companyId", prodProduct.getCompanyId());
            result.put("shopId", shopId);
            result.put("buyNum", buyNum);
            result.put("couponCount", couponCount);
            List<EntityMap> afterSale = aftersaleService.selectByCompanyId(shopId);
            result.put("afterService", afterSale);
            result.put("shopName", prodShop.getShopName());
            result.put("price", price);
            result.put("addressList", addressList);
            result.put("totalAmount", price);
            result.put("totalFreight", totalFreight);
            result.put("payAmount", payAmount);
            result.put("couponUserIds", couponUserIds);
            result.put("totalCouponAmount", totalCouponAmount);

        } finally {
            redisLock.unlock(lock);
        }

        return ResultBody.ok(result);
    }


    /**
     * 商品直接购买提交订单
     *
     * @param params        请求参数
     * @param skuId         商品规格Id
     * @param marketingId   营销商品Id
     * @param addressId     收货地址
     * @param invoiceId     发票
     * @param couponUserIds 优惠券Id,多个逗号隔开
     * @return
     */
    @Override
    public ResultBody orderSub(Map params, Long addressId, Long invoiceId, String couponUserIds, Long skuId, Long marketingId, Integer buyNum, String leaveMsg) {
        ApiAssert.isNotEmpty("收货地址不能为空", addressId);
        ApiAssert.isNotEmpty("购买数量不能为空", buyNum);
        BigDecimal price = null;
        ProdMarketing marketing = null;
        if (FlymeUtils.isNotEmpty(marketingId)) {
            marketing = marketingService.getById(marketingId);
            //取活动价格
            price = marketing.getMarketingPrice();
        }
        return subOrder(params, couponUserIds, addressId, skuId, price, buyNum, leaveMsg, marketing);
    }

    @Override
    public EntityMap couponList(Long skuId, Integer buyNum, Long userId) {
        ApiAssert.gtzero("至少购买1件", buyNum);
        ApiAssert.isNotEmpty("skuId不能为空", skuId);
        ProdSku prodSku = skuService.getById(skuId);
        ApiAssert.isNotEmpty("商品规格不存在", prodSku);
        BigDecimal price = prodSku.getPrice();
        Long productId = prodSku.getProductId();
        ProdProduct prodProduct = productService.getById(productId);
        ApiAssert.isNotEmpty("商品不存在", prodProduct);
        BigDecimal amount = price.multiply(new BigDecimal(buyNum));
        return couponUserService.listByShopIdAndAmount(prodProduct.getShopId(), amount, userId);
    }

    @Override
    public EntityMap countOrderStateByShopId(Long shopId) {
        EntityMap result = new EntityMap();
        CriteriaQuery cq = new CriteriaQuery(OrderInfo.class);
        cq.select("count(orderId) orderCount", "orderState");
        cq.eq(true, "shopId", shopId);
        cq.isNotNull("shopId");
        cq.eq("deleted", CommonConstants.DEL_NO);
        cq.eq("showState", CommonConstants.ENABLED);
        cq.groupBy("orderState");
        List<EntityMap> list = selectEntityMap(cq);
        if (FlymeUtils.isNotEmpty(list)) {
            for (EntityMap entityMap : list) {
                result.put("tab" + entityMap.get("orderState"), entityMap.getInt("orderCount", 0));
            }
        }
        return result;
    }

    @Override
    public EntityMap countOrderStateByUserId(Long userId) {
        EntityMap result = new EntityMap();
        CriteriaQuery cq = new CriteriaQuery(OrderInfo.class);
        cq.select("count(orderId) orderCount", "orderState");
        cq.eq("showState", CommonConstants.ENABLED);
        cq.eq("deleted", CommonConstants.DEL_NO);
        cq.eq(true, "userId", userId);
        cq.groupBy("orderState");
        List<EntityMap> list = selectEntityMap(cq);
        if (FlymeUtils.isNotEmpty(list)) {
            for (EntityMap entityMap : list) {
                result.put("tab" + entityMap.get("orderState"), entityMap.getInt("orderCount", 0));
            }
        }
        return result;
    }


    private ResultBody subOrder(Map params, String couponUserIds, Long addressId, Long skuId, BigDecimal price, Integer buyNum, String leaveMsg, ProdMarketing marketing) {

        Long userId = OpenHelper.getUserId();
        EntityMap result = skuService.findById(skuId);
        Long productId = result.getLong("productId");
        ProdProduct prodProduct = productService.getById(productId);
        if (FlymeUtils.isEmpty(price)) {
            price = result.getBigDecimal("price");
        }
        ApiAssert.isNotEmpty("商品不存在", prodProduct);
        Long shopId = prodProduct.getShopId();
        Long companyId = prodProduct.getCompanyId();
        ApiAssert.isNotEmpty("店铺ID不能为空", shopId);
        //订单总金额
        BigDecimal totalAmount = price.multiply(new BigDecimal(buyNum));
        //总运费
        BigDecimal totalFreight = FlymeUtils.getBigDecimal(prodProduct.getFreight(), "0");
        //总优惠金额
        BigDecimal totalCouponAmount = new BigDecimal("0");
        //实付金额
        BigDecimal payAmount;
        //计算总优惠金额
        if (FlymeUtils.isNotEmpty(couponUserIds)) {
            EntityMap couponMap = couponUserService.calculateCouponAmount(couponUserIds, shopId);
            totalCouponAmount = couponMap.getBigDecimal("totalCouponAmount");
        }
        payAmount = totalAmount.add(totalFreight).subtract(totalCouponAmount);
        ApiAssert.gezero("商品价格设置错误", payAmount);
        OrderInfo orderInfo = new OrderInfo();
        initOrderInfo(orderInfo, payAmount, totalCouponAmount, totalFreight, userId, addressId, totalAmount);
        //订单不需要拆分时赋值店铺ID
        orderInfo.setCompanyId(companyId);
        //子单
        orderInfo.setParentOrder(CommonConstants.DISABLED);
        orderInfo.setShopId(shopId);
        orderInfo.setUserCouponId(couponUserIds);
        orderInfo.setLeaveMsg(leaveMsg);
        orderInfo.setProductCount(buyNum);
        OrderDetails orderDetails = new OrderDetails();
        if (FlymeUtils.isNotEmpty(marketing)) {
            orderDetails.setMarketingId(marketing.getMarketingId());
            orderDetails.setMarketingType(marketing.getMarketingType());
            //营销订单
            orderInfo.setOrderType(2);
        } else {
            //普通订单
            orderInfo.setOrderType(1);
        }
        save(orderInfo);
        orderDetails.setCompanyId(companyId);
        orderDetails.setShopId(shopId);
        orderDetails.setOrderId(orderInfo.getOrderId());
        orderDetails.setSkuId(skuId);
        orderDetails.setUserId(userId);
        orderDetails.setProductId(result.get("productId"));
        orderDetails.setProductPrice(price);
        orderDetails.setProductNum(buyNum);
        orderDetails.setProductAmount(price.multiply(new BigDecimal(buyNum)));
        orderDetails.setEvaluatedState(CommonConstants.DISABLED);
        orderDetails.setAfterSaleState(CommonConstants.DISABLED);

        String images = result.get("images");
        if (FlymeUtils.isEmpty(images) || images.length() < 10) {
            images = prodProduct.getCoverImage();
        }
        orderDetails.setProductImages(images);
        orderDetails.setProductTitle(result.get("title"));
        orderDetails.setSkuTitle(result.get("skuTitle"));
        orderDetailsService.save(orderDetails);

        //保存发票信息
        invoiceService.addInvoide(orderInfo, params);
        //保存收货信息
        logisticsService.add(orderInfo.getReceiveAddressId(), orderInfo.getOrderId());
        //修改优惠券为已使用状态
        couponUserService.updateCouponState(couponUserIds, CommonConstants.ENABLED);
        return ResultBody.ok("订单创建成功", orderInfo);
    }


    /**
     * 订单公共赋值
     *
     * @param orderInfo
     * @param payAmount
     * @param totalCouponAmount
     * @param totalFreight
     * @param userId
     * @param addressId
     * @param totalAmount
     */
    private void initOrderInfo(OrderInfo orderInfo, BigDecimal payAmount, BigDecimal totalCouponAmount, BigDecimal totalFreight, Long userId, Long addressId, BigDecimal totalAmount) {
        orderInfo.setPayAmount(payAmount);
        //优惠金额
        orderInfo.setCouponAmount(totalCouponAmount);
        //运费
        orderInfo.setFreightAmount(totalFreight);
        //下单人
        orderInfo.setUserId(userId);
        //买家收货地址
        orderInfo.setReceiveAddressId(addressId);
        orderInfo.setOrderNo(orderNoUtil.getOrderNo());
        //未删除
        orderInfo.setDeleted(CommonConstants.DEL_NO);
        orderInfo.setDiscountAmount(new BigDecimal("0"));
        //待付款
        orderInfo.setOrderState(OrderStatusEnum.UNPAY.getCode());
        //默认展示,如有拆分则修改为母单
        orderInfo.setShowState(CommonConstants.INT_1);
        //订单总金额
        orderInfo.setTotalAmount(totalAmount);
        orderInfo.setShopScore(CommonConstants.INT_0);
        //未支付
        orderInfo.setPayState(PayStatusEnum.NOPAY.getCode());

    }

    /**
     * 按门店统计销售额
     *
     * @param params 请求参数
     * @return
     */
    @Override
    public ResultBody totalSale(Map params) {
        CriteriaQuery<OrderInfo> cq = new CriteriaQuery(params, OrderInfo.class);
        cq.select(OrderInfo.class, "shopId", "sum(totalAmount) totalAmount", "sum(freightAmount) freightAmount", "sum(couponAmount) couponAmount", "sum(discountAmount) discountAmount", "sum(payAmount) payAmount", "sum(payAmount*shopType.typeRate/100) rateFee", "sum(payAmount-orderinfo.payAmount*shopType.typeRate) cashOutFee");
        cq.select(ProdShop.class, "shopName");
        cq.eq(ProdShop.class, "shopName");
        cq.ge(OrderInfo.class, "payTime", cq.getParams("beginDate"));
        cq.le(OrderInfo.class, "payTime", cq.getParams("endDate"));
        cq.select(ProdShopType.class, "typeName", "typeRate");
        cq.eq(OrderInfo.class, "parentOrder", CommonConstants.DISABLED);
        cq.eq(OrderInfo.class, "deleted", CommonConstants.DEL_NO);
        cq.eq(OrderInfo.class, "payState", PayStatusEnum.PAY.code);
        cq.createJoin(ProdShop.class);
        cq.createJoin(ProdShopType.class).setMainAlias("shop");
        cq.groupBy("orderinfo.shopId");
        return basePageList(cq);
    }

    /**
     * 单个门店销售额明细
     *
     * @param params 请求参数
     * @return
     */
    @Override
    public ResultBody totalSaleByShop(Map params) {
        CriteriaQuery<OrderInfo> cq = new CriteriaQuery(params, OrderInfo.class);
        cq.select(OrderInfo.class, "orderId", "orderNo", "totalAmount", "freightAmount", "couponAmount", "discountAmount", "payAmount", "payTime");
        cq.select("user.userName");
        cq.eq(OrderInfo.class, "shopId", cq.getParams("shopId"));
        cq.le(OrderInfo.class, "payTime", cq.getParams("endDate"));
        cq.ge(OrderInfo.class, "payTime", cq.getParams("beginDate"));
        cq.eq(OrderInfo.class, "parentOrder", CommonConstants.DISABLED);
        cq.eq(OrderInfo.class, "deleted", CommonConstants.DEL_NO);
        cq.eq(OrderInfo.class, "payState", PayStatusEnum.PAY.code);
        cq.createJoin("com.meida.module.user.client.entity.AppUser").setMainField("userId");
        return basePageList(cq);
    }


    /**
     * 统计本年销售情况,按月分组
     *
     * @param params
     * @return
     */
    @Override
    public ResultBody totalSaleByType(Map params) {
        String type = params.getOrDefault("type", "year").toString();
        switch (type) {
            case "year":
                return totalSaleGroupYear(params);
            case "month":
                return totalSaleGroupMonth(params);
            case "week":
                return totalSaleGroupWeek(params);
            case "day":
                return totalSaleGroupDays(params);
        }

        return null;
    }

    /**
     * 统计本年销售情况,按月分组
     *
     * @param params
     * @return
     */
    private ResultBody totalSaleGroupYear(Map params) {
        Long companyId = OpenHelper.getCompanyId();
        String year = params.getOrDefault("year", DateUtils.getYear()).toString();
        CriteriaQuery cq = new CriteriaQuery(params, OrderInfo.class);
        cq.select("MONTH(createTime) orderMonth", "count(orderId) orderCount", "sum(totalAmount) totalAmount");
        cq.eq("YEAR(createTime)", year);
        cq.eq("parentOrder", CommonConstants.DISABLED);
        cq.eq("deleted", CommonConstants.DEL_NO);
        //cq.eq( "payState", PayStatusEnum.PAY.code);
        Integer superAdmin = OpenHelper.getUser().getSuperAdmin();
        if (FlymeUtils.isNotEmpty(companyId) && superAdmin.equals(0)) {
            cq.eq(true, "companyId", companyId);
        }
        cq.groupBy("orderMonth");
        cq.orderByAsc("createTime");
        List<Map<String, Object>> list = listMaps(cq);
        //销售额
        List<Map<String, Object>> amountList = new ArrayList<>();
        //销售量
        List<Map<String, Object>> countList = new ArrayList<>();

        for (int i = 1; i <= 12; i++) {
            Map<String, Object> amountMap = new HashMap<>();
            Map<String, Object> countMap = new HashMap<>();
            amountMap.put("x", i + "月");
            countMap.put("x", i + "月");
            amountMap.put("y", 0);
            countMap.put("y", 0);
            for (Map<String, Object> map : list) {
                String totalAmount = map.get("totalAmount").toString();
                String orderCount = map.get("orderCount").toString();
                int month = FlymeUtils.getInteger(map.get("orderMonth").toString(), 0);
                if (month == i) {
                    amountMap.put("y", new BigDecimal(totalAmount));
                    countMap.put("y", Integer.parseInt(orderCount));
                }
            }
            amountList.add(amountMap);
            countList.add(countMap);
        }

        EntityMap result = new EntityMap();
        result.put("amountList", amountList);
        result.put("countList", countList);
        EntityMap saleMap = totalOrderByYear(params, "year");
        result.putAll(saleMap);
        return ResultBody.ok(result);
    }

    /**
     * 统计本日销售情况,按小时分组
     *
     * @param params
     * @return
     */
    private ResultBody totalSaleGroupDays(Map params) {
        EntityMap result = new EntityMap();
        CriteriaQuery cq = new CriteriaQuery(params, OrderInfo.class);
        cq.select("DATE_FORMAT( createTime, '%Y-%m-%d %H' ) AS time", "DATE_FORMAT( createTime, '%H' ) AS hours", "count(orderId) orderCount", "sum(totalAmount) totalAmount");
        cq.eq("to_days(createTime)", DateUtils.toDays());
        cq.groupBy("time");
        List<EntityMap> list = selectEntityMap(cq);
        //销售额
        List<Map<String, Object>> amountList = new ArrayList<>();
        //销售量
        List<Map<String, Object>> countList = new ArrayList<>();

        for (int i = 0; i <= 24; i++) {
            Map<String, Object> amountMap = new HashMap<>();
            Map<String, Object> countMap = new HashMap<>();
            amountMap.put("x", i + "点");
            countMap.put("x", i + "点");
            amountMap.put("y", 0);
            countMap.put("y", 0);
            for (Map<String, Object> map : list) {
                String totalAmount = map.get("totalAmount").toString();
                String orderCount = map.get("orderCount").toString();
                int hours = FlymeUtils.getInteger(map.get("hours").toString(), 0);
                if (hours == i) {
                    amountMap.put("y", new BigDecimal(totalAmount));
                    countMap.put("y", Integer.parseInt(orderCount));
                }
            }
            amountList.add(amountMap);
            countList.add(countMap);
        }
        result.put("amountList", amountList);
        result.put("countList", countList);
        EntityMap saleMap = totalOrderByYear(params, "day");
        result.putAll(saleMap);
        return ResultBody.ok(result);
    }

    /**
     * 统计本周销售情况,按天分组
     *
     * @param params
     * @return
     */
    private ResultBody totalSaleGroupWeek(Map params) {
        EntityMap result = new EntityMap();
        String beign = DateUtils.getFirstDayOfWeek().toString();
        CriteriaQuery cq = new CriteriaQuery(params, OrderInfo.class);
        cq.select("DATE_FORMAT( createTime, '%Y-%m-%d' ) AS time", "count(orderId) orderCount", "sum(totalAmount) totalAmount");
        cq.ge("createTime", beign);
        cq.le("createTime", DateUtils.getLastDayOfWeek().toString());
        cq.groupBy("time");
        List<EntityMap> list = selectEntityMap(cq);
        //销售额
        List<Map<String, Object>> amountList = new ArrayList<>();
        //销售量
        List<Map<String, Object>> countList = new ArrayList<>();

        for (int i = 0; i < 7; i++) {
            String date = DateUtils.getDayOfWeek(DateUtils.plusDays(DateUtils.getFirstDayOfWeek(), i));
            Map<String, Object> amountMap = new HashMap<>();
            Map<String, Object> countMap = new HashMap<>();
            amountMap.put("x", date);
            countMap.put("x", date);
            amountMap.put("y", 0);
            countMap.put("y", 0);
            for (Map<String, Object> map : list) {
                String totalAmount = map.get("totalAmount").toString();
                String orderCount = map.get("orderCount").toString();
                String d = map.get("time").toString();
                if (d.equals(date)) {
                    amountMap.put("y", new BigDecimal(totalAmount));
                    countMap.put("y", Integer.parseInt(orderCount));
                }
            }
            amountList.add(amountMap);
            countList.add(countMap);
        }
        result.put("amountList", amountList);
        result.put("countList", countList);
        EntityMap saleMap = totalOrderByYear(params, "week");
        result.putAll(saleMap);
        return ResultBody.ok(result);
    }

    /**
     * 统计本月销售情况,按天分组
     *
     * @param params
     * @return
     */
    private ResultBody totalSaleGroupMonth(Map params) {
        EntityMap result = new EntityMap();
        String beign = DateUtils.getFirstDayOfMonth().toString();
        CriteriaQuery cq = new CriteriaQuery(params, OrderInfo.class);
        cq.select("DATE_FORMAT( createTime, '%Y-%m-%d' ) AS time", "count(orderId) orderCount", "sum(totalAmount) totalAmount");
        cq.ge("createTime", beign);
        cq.le("createTime", DateUtils.getLastDayOfMonth().toString());
        cq.groupBy("time");
        List<EntityMap> list = selectEntityMap(cq);
        //销售额
        List<Map<String, Object>> amountList = new ArrayList<>();
        //销售量
        List<Map<String, Object>> countList = new ArrayList<>();
        int num = DateUtils.getMonthDaysNum();
        for (int i = 0; i < num; i++) {
            String date = DateUtils.plusDays(DateUtils.getFirstDayOfMonth(), i);
            Map<String, Object> amountMap = new HashMap<>();
            Map<String, Object> countMap = new HashMap<>();
            amountMap.put("x", date);
            countMap.put("x", date);
            amountMap.put("y", 0);
            countMap.put("y", 0);
            for (Map<String, Object> map : list) {
                String totalAmount = map.get("totalAmount").toString();
                String orderCount = map.get("orderCount").toString();
                String d = map.get("time").toString();
                if (d.equals(date)) {
                    amountMap.put("y", new BigDecimal(totalAmount));
                    countMap.put("y", Integer.parseInt(orderCount));
                }
            }
            amountList.add(amountMap);
            countList.add(countMap);
        }
        result.put("amountList", amountList);
        result.put("countList", countList);
        EntityMap saleMap = totalOrderByYear(params, "month");
        result.putAll(saleMap);
        return ResultBody.ok(result);
    }

    /**
     * 统计订单销售排名,平台按店铺分组排名，店铺按商品分组排名,按月分组
     *
     * @param params
     * @return
     */
    private EntityMap totalOrderByYear(Map params, String type) {
        EntityMap result = new EntityMap();
        Long companyId = OpenHelper.getCompanyId();
        CriteriaQuery cq = new CriteriaQuery(params, OrderDetails.class);
        Integer superAdmin = OpenHelper.getUser().getSuperAdmin();
        cq.select("count(details.orderDetailsId) saleCount", "sum(details.productPrice*details.productNum) saleAmount");
        if (FlymeUtils.isNotEmpty(companyId) && superAdmin.equals(0)) {
            cq.select(ProdProduct.class, "productName name");
            cq.eq(true, "details.shopId", companyId);
            cq.createJoin(ProdProduct.class);
            cq.groupBy("details.productId");
            cq.orderByDesc("saleAmount");
        } else {
            cq.select(ProdShop.class, "shopName name");
            cq.createJoin(ProdShop.class);
            cq.groupBy("details.shopId");
            cq.orderByDesc("saleAmount");
        }
        switch (type) {
            case "year":
                cq.eq("YEAR(details.createTime)", DateUtils.getYear());
                break;
            case "month":
                cq.ge("details.createTime", DateUtils.getFirstDayOfMonth().toString());
                cq.le("details.createTime", DateUtils.getLastDayOfMonth().toString());
                break;
            case "week":
                cq.ge("details.createTime", DateUtils.getFirstDayOfWeek().toString());
                cq.le("details.createTime", DateUtils.getLastDayOfWeek().toString());
                break;
            case "day":
                cq.eq("to_days(details.createTime)", DateUtils.toDays());
                break;
        }

        cq.limit(7);
        List<EntityMap> list = orderDetailsService.selectEntityMap(cq);
        List<EntityMap> saleAmountList = new ArrayList<>();
        List<EntityMap> saleCountList = new ArrayList<>();
        if (FlymeUtils.isNotEmpty(list)) {
            for (EntityMap entityMap : list) {
                EntityMap amountMap = new EntityMap();
                EntityMap countMap = new EntityMap();
                BigDecimal amount = entityMap.getBigDecimal("saleAmount");
                Integer count = entityMap.getInt("saleCount");
                String name = entityMap.get("name");
                amountMap.put("name", name);
                amountMap.put("total", amount);
                countMap.put("name", name);
                countMap.put("total", count);
                saleAmountList.add(amountMap);
                saleCountList.add(countMap);
            }
            saleCountList = saleCountList.stream().sorted(Comparator.comparing(OrderInfoServiceImpl::comparingByName).reversed()).collect(Collectors.toList());
        }
        result.put("saleAmountList", saleAmountList);
        result.put("saleCountList", saleCountList);
        return result;
    }


    private static Integer comparingByName(EntityMap map) {
        return map.getInt("total", 0);
    }


    /**
     * 统计订单销售排名,平台按店铺分组排名，店铺按商品分组排名,按月分组
     *
     * @param params
     * @return
     */

    public ResultBody getSaleByCateGory(Map params) {
        EntityMap result = new EntityMap();
        Long companyId = OpenHelper.getCompanyId();
        CriteriaQuery cq = new CriteriaQuery(params, OrderDetails.class);
        cq.select("sum(details.productPrice*details.productNum) saleAmount");

        Integer superAdmin = OpenHelper.getUser().getSuperAdmin();
        if (FlymeUtils.isNotEmpty(companyId) && superAdmin.equals(0)) {
            cq.eq(true,"details.companyId", companyId);
        }
        EntityMap totalMap = findOne(cq);

        cq.select(ProdCategory.class, "categoryName");
        cq.createJoin(ProdCategory.class).setMainField("categoryId1");
        cq.groupBy("details.categoryId1");
        List<EntityMap> list = orderDetailsService.selectEntityMap(cq);

        List<EntityMap> saleList = new ArrayList<>();
        if (FlymeUtils.isNotEmpty(list)) {
            BigDecimal totalAmount = totalMap.getBigDecimal("saleAmount");
            for (EntityMap entityMap : list) {
                EntityMap item = new EntityMap();
                BigDecimal amount = entityMap.getBigDecimal("saleAmount");

                BigDecimal blli = amount.divide(totalAmount, RoundingMode.HALF_UP);
                String categoryName = entityMap.get("categoryName");
                item.put("item", categoryName);
                item.put("count", blli);
                saleList.add(item);
            }
        }
        result.put("saleList", saleList);
        return ResultBody.ok(result);
    }


    @Override
    public ResultBody getTotalData(Map params) {
        EntityMap result = new EntityMap();
        Long companyId = OpenHelper.getCompanyId();
        EntityMap totalMap = totalSales(companyId);
        result.putAll(totalMap);

        //月同比统计
        EntityMap totalThisMonth = totalThisMonth(companyId);
        EntityMap totalMonthByTongBi = totalMonthByTongBi(companyId);

        //日环比统计
        EntityMap totalToday = totalThisMonth(companyId);
        EntityMap totalYesterDay = totalMonthByTongBi(companyId);


        //月销售金额
        BigDecimal thisMonthAmount = totalThisMonth.getBigDecimal("totalAmount");
        BigDecimal monthByTongBiAmount = totalThisMonth.getBigDecimal("totalAmount");

        //月销售数量
        BigDecimal thisMonthCount = totalThisMonth.getBigDecimal("totalCount");
        BigDecimal monthByTongBiCount = totalThisMonth.getBigDecimal("totalCount");

        //天销售金额
        BigDecimal totalTodayAmount = totalToday.getBigDecimal("totalAmount");
        BigDecimal totalYesterDayAmount = totalYesterDay.getBigDecimal("totalAmount");

        //天销售数量
        BigDecimal totalTodayCount = totalToday.getBigDecimal("totalCount");
        BigDecimal totalYesterDayCount = totalYesterDay.getBigDecimal("totalCount");

        //计算销售金额月同比
        BigDecimal tbAmount = new BigDecimal("0");
        String monthAmountFlag = "down";
        if (FlymeUtils.gtzero(monthByTongBiAmount)) {
            tbAmount = (thisMonthAmount.subtract(monthByTongBiAmount)).divide(monthByTongBiAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
        } else {
            if (FlymeUtils.gtzero(thisMonthAmount)) {
                tbAmount = new BigDecimal("100");
            }
        }
        if (FlymeUtils.gtzero(tbAmount)) {
            monthAmountFlag = "up";
        }
        result.put("monthAmountFlag", monthAmountFlag);
        result.put("tbAmount", tbAmount);


        //计算销售数量月同比
        BigDecimal tbCount = new BigDecimal("0");
        String monthCountFlag = "down";
        if (FlymeUtils.gtzero(monthByTongBiAmount)) {
            tbCount = (thisMonthCount.subtract(monthByTongBiCount)).divide(monthByTongBiCount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
        } else {
            if (FlymeUtils.gtzero(thisMonthCount)) {
                tbCount = new BigDecimal("100");
            }
        }
        if (FlymeUtils.gtzero(tbAmount)) {
            monthCountFlag = "up";
        }
        result.put("monthCountFlag", monthCountFlag);
        result.put("tbCount", tbCount);


        //计算销售金额日环比
        BigDecimal hbAmount = new BigDecimal("0");
        String dayAmountFlag = "down";
        if (FlymeUtils.gtzero(totalYesterDayAmount)) {
            hbAmount = (totalTodayAmount.subtract(totalYesterDayAmount)).divide(totalYesterDayAmount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
        } else {
            if (FlymeUtils.gtzero(totalTodayAmount)) {
                hbAmount = new BigDecimal("100");
            }
        }
        if (FlymeUtils.gtzero(hbAmount)) {
            dayAmountFlag = "up";
        }
        result.put("dayAmountFlag", dayAmountFlag);
        result.put("hbAmount", hbAmount);
        result.put("totalTodayAmount", totalTodayAmount);


        //计算销售数量日环比
        BigDecimal hbCount = new BigDecimal("0");
        String dayCountFlag = "down";
        if (FlymeUtils.gtzero(totalYesterDayCount)) {
            hbCount = (totalTodayCount.subtract(totalYesterDayCount)).divide(totalYesterDayCount, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
        } else {
            if (FlymeUtils.gtzero(totalTodayAmount)) {
                hbCount = new BigDecimal("100");
            }
        }
        if (FlymeUtils.gtzero(hbCount)) {
            dayCountFlag = "up";
        }
        result.put("dayCountFlag", dayCountFlag);
        result.put("hbCount", hbCount);
        result.put("totalTodayCount", totalTodayCount);


        return ResultBody.ok(result);
    }

    @Override
    public EntityMap totalSales(Long comapnyId) {
        OpenUser openUser = OpenHelper.getUser();
        Integer superAdmin = openUser.getSuperAdmin();
        Long companyId = openUser.getCompanyId();
        CriteriaQuery cq = new CriteriaQuery(OrderInfo.class);
        cq.eq("showState", CommonConstants.INT_1);
        cq.eq("deleted", CommonConstants.DEL_NO);
        cq.select("sum(totalAmount) totalAmount", "count(orderId) orderCount");
        if (FlymeUtils.isNotEmpty(comapnyId) && superAdmin.equals(0)) {
            cq.eq(true, "companyId", comapnyId);
        }
        return findOne(cq);
    }

    /**
     * 统计今日销售额
     *
     * @param comapnyId
     * @return
     */
    private EntityMap totalToday(Long comapnyId) {
        CriteriaQuery cq = new CriteriaQuery(OrderInfo.class);
        cq.select("sum(totalAmount) todayAmount", "count(orderId) todayCount");
        long todays = DateUtils.toDays();
        cq.eq("to_days(createTime)", todays);
        cq.eq("showState", CommonConstants.INT_1);
        cq.eq("deleted", CommonConstants.DEL_NO);
        Integer superAdmin = OpenHelper.getUser().getSuperAdmin();
        if (FlymeUtils.isNotEmpty(comapnyId) && superAdmin.equals(0)) {
            cq.eq(true, "companyId", comapnyId);
        }
        return findOne(cq);
    }

    /**
     * 统计昨天日销售额
     *
     * @param comapnyId
     * @return
     */
    private EntityMap totalYesterDay(Long comapnyId) {
        CriteriaQuery cq = new CriteriaQuery(OrderInfo.class);
        cq.select("sum(totalAmount) yesterDayAmount", "count(orderId) yesterDayCount");
        long todays = DateUtils.toDays();
        cq.eq("datediff(createTime,now())", -1);
        cq.eq("showState", CommonConstants.INT_1);
        cq.eq("deleted", CommonConstants.DEL_NO);
        Integer superAdmin = OpenHelper.getUser().getSuperAdmin();
        if (FlymeUtils.isNotEmpty(comapnyId) && superAdmin.equals(0)) {
            cq.eq(true, "companyId", comapnyId);
        }
        return findOne(cq);
    }


    /**
     * 统计本月销售额
     *
     * @param comapnyId
     * @return
     */
    private EntityMap totalThisMonth(Long comapnyId) {
        CriteriaQuery cq = new CriteriaQuery(OrderInfo.class);
        cq.select("sum(totalAmount) yesterDayAmount", "count(orderId) yesterDayCount");
        long todays = DateUtils.toDays();
        String begin = DateUtils.getFirstDayOfMonth().toString();
        String end = DateUtils.getLastDayOfMonth().toString();
        Integer superAdmin = OpenHelper.getUser().getSuperAdmin();
        if (FlymeUtils.isNotEmpty(comapnyId) && superAdmin.equals(0)) {
            cq.eq(true, "companyId", comapnyId);
        }
        cq.eq("showState", CommonConstants.INT_1);
        cq.eq("deleted", CommonConstants.DEL_NO);
        cq.ge("createTime", begin);
        cq.le("createTime", end);
        return findOne(cq);
    }

    /**
     * 统计本月同比销售额
     *
     * @param comapnyId
     * @return
     */
    private EntityMap totalMonthByTongBi(Long comapnyId) {
        CriteriaQuery cq = new CriteriaQuery(OrderInfo.class);
        cq.select("sum(totalAmount) yesterDayAmount", "count(orderId) yesterDayCount");
        String begin = DateUtils.getMonthFirstDayByTongBi();
        String end = DateUtils.getMonthLastDayByTongBi();
        Integer superAdmin = OpenHelper.getUser().getSuperAdmin();
        if (FlymeUtils.isNotEmpty(comapnyId) && superAdmin.equals(0)) {
            cq.eq(true, "companyId", comapnyId);
        }
        cq.eq("showState", CommonConstants.INT_1);
        cq.eq("deleted", CommonConstants.DEL_NO);
        cq.ge("createTime", begin);
        cq.le("createTime", end);
        return findOne(cq);
    }

}
